package com.jiunuan.live.im.router.provider.service.impl;

import com.jiunuan.live.framework.redis.starter.key.IMCoreServerProviderCacheKeyBuilder;
import com.jiunuan.live.im.core.server.interfaces.constants.ImCoreServerConstants;
import com.jiunuan.live.im.core.server.interfaces.rpc.IRouterHandlerRpc;
import com.jiunuan.live.im.dto.ImMsgBody;
import com.jiunuan.live.im.router.provider.service.ImRouterService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: JiuNuan
 * @CreateTime: 2024-08-16 11:55
 * @Description:
 */
@Service
public class ImRouterServiceImpl implements ImRouterService {
    @DubboReference
    private IRouterHandlerRpc routerHandlerRpc;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IMCoreServerProviderCacheKeyBuilder cacheKeyBuilder;
    /**
     * 按照用户id进行消息的发送
     *
     * @param imMsgBody
     */
    @Override
    public boolean sendMsg(ImMsgBody imMsgBody) {
        // 假设有100个userId -> 10台im服务器， 100个ip分类 -> 最终ip数量一定 <=10
        String bindAddress = stringRedisTemplate.opsForValue().get(cacheKeyBuilder.buildIMBindIpKey(imMsgBody.getAppId(),imMsgBody.getUserId()));
        if(StringUtils.isEmpty(bindAddress)){
            return false;
        }
        // 截取ip   组成方式为 ip%userId
        bindAddress = bindAddress.substring(bindAddress.indexOf("%"));
        RpcContext.getContext().set("ip", bindAddress);
        routerHandlerRpc.sendMsg(imMsgBody);
        return true;
    }

    /**
     * 支持批量发送消息，群聊场景
     *
     * @param imMsgBodyList 消息体列表，包含所有用户的消息
     */
    @Override
    public void batchSendMsg(List<ImMsgBody> imMsgBodyList) {
        // 提取所有用户ID
        List<Long> userIdList = imMsgBodyList.stream().map(ImMsgBody::getUserId).collect(Collectors.toList());
        // 用户ID与消息体映射
        Map<Long, ImMsgBody> userIdMsgMap = imMsgBodyList.stream().collect(Collectors.toMap(ImMsgBody::getUserId, x -> x));
        // 保证整个列表的appId一致
        Integer appId = imMsgBodyList.get(0).getAppId();
        List<String> cacheKeyList = new ArrayList<>();
        // 生成缓存键值列表
        userIdList.forEach(userId -> {
            String cacheKeyPrefix = cacheKeyBuilder.buildIMBindIpKey(appId, userId);
            cacheKeyList.add(cacheKeyPrefix);
        });
        //批量取出每个用户绑定的ip地址
//        List<String> ipList = stringRedisTemplate.opsForValue().multiGet(cacheKeyList);
        List<String> ipList = stringRedisTemplate.opsForValue().multiGet(cacheKeyList).stream().filter(x -> x != null).collect(Collectors.toList());
        Map<String, List<Long>> userIdMap = new HashMap<>();
        // 解析IP地址和用户ID
        ipList.forEach(ip -> {
            String currentIp = ip.substring(0, ip.indexOf("%"));
            Long userId = Long.valueOf(ip.substring(ip.indexOf("%") + 1));
            List<Long> currentUserIdList = userIdMap.get(currentIp);
            if (currentUserIdList == null) {
                currentUserIdList = new ArrayList<>();
            }
            currentUserIdList.add(userId);
            userIdMap.put(currentIp, currentUserIdList);
        });

        // 按IP地址分组发送消息
        userIdMap.keySet().forEach(currentIp -> {
            RpcContext.getContext().set("ip", currentIp);
            List<ImMsgBody> batchSendMsgGroupByIpList = new ArrayList<>();
            List<Long> ipBindUserIdList = userIdMap.get(currentIp);
            ipBindUserIdList.forEach(userId -> {
                ImMsgBody imMsgBody = userIdMsgMap.get(userId);
                batchSendMsgGroupByIpList.add(imMsgBody);
            });
            routerHandlerRpc.batchSendMsg(batchSendMsgGroupByIpList);
        });
    }

}
